﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Index;
using Lucene.Net.Analysis;
using System.IO;
using Lucene.Net.Documents;
using Lucene.Net.Search;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.QueryParsers;
using System.Diagnostics;
using Lucene.Net.Util;
using LuceneIO = Lucene.Net.Store;

namespace Lucene
{
    public abstract class SearchBase
    {
        protected Analyzer analyzer = null;
        protected DirectoryInfo dirInfo = null;
        protected LuceneIO.Directory directory = null;
        protected IndexSearcher searcher = null;
        public SearchBase()
        {
            analyzer = new StandardAnalyzer();
            dirInfo = Directory.CreateDirectory(Config.INDEX_STORE_PATH);
            directory = LuceneIO.FSDirectory.Open(dirInfo);
            searcher = new IndexSearcher(Config.INDEX_STORE_PATH);
        }

        #region 检索的方式

        /// <summary>
        /// 对单个文件进行检索
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        protected virtual TopDocs TermQuery(string keyword, string field, int? pagesize)
        {
            TopDocs docs = null;
            try
            {
                Term t = new Term(field, keyword);
                Query query = new TermQuery(t);
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10);

            }
            catch (Exception ex)
            {
                docs = null;
                throw;
            }
            return docs;
        }

        /// <summary>
        /// 范围检索
        /// </summary>
        /// <param name="field"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="isInclude"></param>
        /// <returns></returns>
        protected virtual TopDocs RangeQuery(string field, string start, string end, bool isInclude, int? pagesize)
        {
            TopDocs docs = null;
            try
            {
                Term beginT = new Term(field, start);
                Term endT = new Term(field, end);
                Query query = new RangeQuery(beginT, endT, isInclude);
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10);
            }
            catch (Exception)
            {
                docs = null;
                throw;
            }
            return docs;
        }

        /// <summary>
        /// 检索满足多个条件的
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        protected virtual TopDocs BooleanQuery(string keyword, string field, int? pagesize)
        {
            string[] words = keyword.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            TopDocs docs = null;
            try
            {
                BooleanQuery boolQuery = new BooleanQuery();
                for (int i = 0; i < words.Length; i++)
                {
                    TermQuery tq = new TermQuery(new Term(field, words[i]));//termquery
                    boolQuery.Add(tq, BooleanClause.Occur.MUST);
                }
                docs = searcher.Search(boolQuery, (Filter)null, pagesize ?? 10);

            }
            catch (Exception)
            {
                docs = null;
                throw;
            }
            return docs;
        }

        /// <summary>
        /// 是否包含某个前缀
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        protected virtual TopDocs PrefixQuery(string keyword, string field, int? pagesize)
        {
            TopDocs docs = null;
            try
            {
                Term t = new Term(field, keyword);
                PrefixQuery query = new PrefixQuery(t);
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10);
            }
            catch (Exception)
            {
                docs = null;
                throw;
            }
            return docs;
        }

        /// <summary>
        /// 通配符功能
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        protected virtual TopDocs WildcardQuery(string keyword, string field, int? pagesize)
        {
            TopDocs docs = null;
            try
            {
                Term t = new Term(field, keyword);
                WildcardQuery query = new WildcardQuery(t);
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10);
            }
            catch (Exception)
            {
                docs = null;
                throw;
            }
            return docs;
        }


        /// <summary>
        /// 多字段搜索(以空格，逗号等分隔符隔开)
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        protected virtual TopDocs MulFieldsSearch(string keyword, string[] fields, int? pagesize)
        {
            TopDocs docs = null;

            try
            {
                BooleanClause.Occur[] flags = new BooleanClause.Occur[] { BooleanClause.Occur.MUST, BooleanClause.Occur.MUST };
                string[] values = keyword.Trim().Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (fields.Length != values.Length)
                {
                    throw new Exception("字段和对应值不一致");
                }
                //MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
                //parser.SetDefaultOperator(QueryParser.Operator.OR);//或者的关系
                //Query query = parser.Parse(keyword);
                Query query = MultiFieldQueryParser.Parse(values, fields, flags, new StandardAnalyzer());
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10); //排序获取搜索结果
            }
            catch (Exception)
            {
                throw;
            }
            return docs;
        }


        /// <summary>
        /// 根据多个索引文件夹搜索
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        protected virtual TopDocs MultiSearch(string keyword, string field, Searchable[] abs, int? pagesize)
        {
            TopDocs docs = null;
            MultiSearcher searcher = new MultiSearcher(abs);//构造MultiSearcher
            try
            {
                QueryParser parser = new QueryParser(field, new StandardAnalyzer());
                Query query = parser.Parse(keyword);
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10); //排序获取搜索结果
            }
            catch (Exception ex)
            {
                docs = null;
                throw;
            }
            return docs;
        }



        /// <summary>
        /// 根据索引排序搜索
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        protected virtual TopDocs SortSearch(string keyword, string field, bool sortFlag, int? pagesize)
        {
            TopDocs docs = null;
            try
            {
                QueryParser parser = new QueryParser(field, new StandardAnalyzer());//针对内容查询
                Query query = parser.Parse(keyword);//搜索内容 contents  (用QueryParser.Parse方法实例化一个查询)
                Stopwatch watch = new Stopwatch();
                bool sortDirection = true;

                if (sortFlag)//按照id升序
                {
                    sortDirection = false;
                }
                watch.Start();
                Sort sort = new Sort();
                SortField sf = new SortField("id", SortField.INT, sortDirection);//按照id字段排序，false表示升序,ture表示逆序
                //SortField sf = new SortField("filename", SortField.DOC, false);//按照filename字段排序，false表示升序

                sort.SetSort(sf);

                //多个条件排序
                //Sort sort = new Sort();
                //SortField f1 = new SortField("id", SortField.INT, false);
                //SortField f2 = new SortField("filename", SortField.DOC, false);
                //sort.SetSort(new SortField[] { f1, f2 });
                docs = searcher.Search(query, (Filter)null, pagesize ?? 10, sort); //排序获取搜索结果

            }
            catch (Exception)
            {
                docs = null;
                throw;
            }
            return docs;
        }
        #endregion
    }
}
